package edu.uwm.capstone.diasmart;

import java.util.Calendar;
import java.util.Date;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TabHost;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.TimePicker;
import edu.uwm.capstone.android.util.DialogUtil;
import edu.uwm.capstone.android.widgets.WidgetChangeDetector;
import edu.uwm.capstone.diasmart.database.Category;
import edu.uwm.capstone.diasmart.database.DatabaseHelper;
import edu.uwm.capstone.diasmart.database.Entry;
import edu.uwm.capstone.diasmart.database.SubType;
import edu.uwm.capstone.diasmart.types.EditableEntryType;
import edu.uwm.capstone.diasmart.types.EntryContext;
import edu.uwm.capstone.diasmart.types.EntryType;
import edu.uwm.capstone.diasmart.types.EntryTypeFactory;
import edu.uwm.capstone.diasmart.util.AddEntryHelper;
import edu.uwm.capstone.diasmart.util.Common;
import edu.uwm.capstone.util.DateUtil;
import edu.uwm.capstone.util.DebugUtil;
import edu.uwm.capstone.util.StringUtil;

@SuppressWarnings("unused")
public class AddEditEntryActivity extends Activity {
	private Button btnEditDate;
	private Button btnEditTime;
	private DatePickerDialog.OnDateSetListener startDateSetListener;
	private TimePickerDialog.OnTimeSetListener startTimeSetListener;
	private Calendar entryDate;
	private WidgetChangeDetector changes;
	private java.text.DateFormat dateFormat;
	private java.text.DateFormat timeFormat;
	private Category[] categories = null;

	private EditText edtNote;
	private EditText edtValue;
	private Entry entry = null;
	private TableRow trowSubTypes;

	private Spinner sprTypes;
	private Spinner sprCategories;
	private Spinner sprReminder;
	private Spinner sprSubTypes;

	private String errorMessage;

	private int entryType = -1;
	private int mode = 0;
	private int lastEntryType = -1;
	private boolean insertMode = true;

	private void initialize(DatabaseHelper dh) {
		DebugUtil.debug(this, "Initializing elements in AddEditEntryActivity");

		/*
		 * Initialize the variables
		 */
		this.entryDate = Calendar.getInstance();
		this.btnEditDate = (Button) findViewById(R.id.btnEditDate);
		this.btnEditTime = ((Button) findViewById(R.id.btnEditTime));
		this.edtValue = (EditText) findViewById(R.id.edtValue);
		this.edtNote = (EditText) findViewById(R.id.edtNote);
		this.sprTypes = (Spinner) findViewById(R.id.sprType);
		this.sprSubTypes = (Spinner) findViewById(R.id.sprSubType);
		this.sprReminder = (Spinner) findViewById(R.id.sprReminder);
		this.trowSubTypes = ((TableRow) findViewById(R.id.trowSubType));
		this.sprCategories = (Spinner) findViewById(R.id.sprCategory);
		this.changes = new WidgetChangeDetector(
				(ViewGroup) findViewById(R.id.root));
		this.entry = new Entry();

		/*
		 * Initialize the tabs
		 */
		TabHost tabHost = (TabHost) findViewById(R.id.tabhost);
		tabHost.setup();
		TabHost.TabSpec mainspec = tabHost.newTabSpec("Main");
		if (this.mode == 0)
			mainspec.setIndicator("Add Entry",
					getResources().getDrawable(R.drawable.ic_tab_main));
		else
			mainspec.setIndicator("Edit Entry",
					getResources().getDrawable(R.drawable.ic_tab_main));
		mainspec.setContent(R.id.editTab);
		// Add Main as heading to tab1
		tabHost.addTab(mainspec);

		mainspec = tabHost.newTabSpec("Notes");
		mainspec.setIndicator("Notes",
				getResources().getDrawable(R.drawable.ic_tab_notes));
		mainspec.setContent(R.id.noteTab);
		// Add Notes as heading to tab2
		tabHost.addTab(mainspec);
		tabHost.setCurrentTab(0);

		/*
		 * Initialized the date and time button
		 */
		updateButtonEntryDate();

		this.btnEditDate.setOnClickListener(new View.OnClickListener() {
			@SuppressWarnings("deprecation")
			public void onClick(View paramAnonymousView) {
				DebugUtil.debug(this,
						"Setting OnClick Listener for button Edit Date");
				AddEditEntryActivity.this.showDialog(0);

			}
		});
		this.startDateSetListener = new DatePickerDialog.OnDateSetListener() {
			public void onDateSet(DatePicker view, int year, int monthOfYear,
					int dayOfMonth) {
				DebugUtil.debug(this, "OnDateSet called: year = " + year
						+ " month = " + monthOfYear + " day = " + dayOfMonth);
				Calendar rightNow = Calendar.getInstance();
				DateUtil.trimTime(rightNow);
				rightNow.set(year, monthOfYear, dayOfMonth);
				if (!DateUtil.isCalendarValid(rightNow)) {
					DialogUtil.createErrorDialog(AddEditEntryActivity.this,
							R.string.error, R.string.invalid_date).show();
				}
				Calendar today = Calendar.getInstance();
				DateUtil.trimTime(today);
				today.add(6, 1);
				if (rightNow.after(today)) {
					String str = AddEditEntryActivity.this
							.getString(R.string.future_date);
					DialogUtil.createErrorDialog(AddEditEntryActivity.this,
							R.string.error, str).show();
				}
				AddEditEntryActivity.this.entryDate.set(year, monthOfYear,
						dayOfMonth);
				AddEditEntryActivity.this.updateButtonEntryDate();
				AddEditEntryActivity.this.changes.setChanged();
			}
		};

		// Time Listener

		this.btnEditTime.setOnClickListener(new View.OnClickListener() {
			@SuppressWarnings("deprecation")
			public void onClick(View paramAnonymousView) {
				DebugUtil.debug(this,
						"Setting OnClick Listener for button Edit Time");
				AddEditEntryActivity.this.showDialog(1);
			}
		});
		this.startTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
			public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
				DebugUtil.debug(this, "OnDateSet called: Hour = " + hourOfDay
						+ " Minute = " + minute);
				AddEditEntryActivity.this.entryDate.set(11, hourOfDay);
				AddEditEntryActivity.this.entryDate.set(12, minute);
				AddEditEntryActivity.this.updateButtonEntryDate();
				AddEditEntryActivity.this.changes.setChanged();

				DatabaseHelper dh = new DatabaseHelper(
						AddEditEntryActivity.this);
				try {
					Category category = dh.getCategoryDAO().getInitialCategory(
							AddEditEntryActivity.this.categories,
							AddEditEntryActivity.this.entryDate.getTime(),
							false);
					if (category != null) {
						AddEntryHelper.updateCategorySelection(
								AddEditEntryActivity.this.sprCategories,
								category.getId());
					}
				} catch (Exception e) {
					DebugUtil.debug(this, e.getLocalizedMessage());
				} finally {
					dh.close();
				}

			}
		};

		Common.setNumericKeyboardType(this, this.edtValue, "preference");

		ArrayAdapter<EntryType> typesAdapter = new ArrayAdapter<EntryType>(
				this, android.R.layout.simple_spinner_item,
				EntryTypeFactory.getVisibleTypes(new EntryContext(this)));
		typesAdapter
				.setDropDownViewResource(android.R.layout.simple_spinner_item);
		this.sprTypes.setAdapter(typesAdapter);
		this.sprTypes.setPromptId(R.string.type);
		this.sprTypes
				.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
					public void onItemSelected(AdapterView<?> adapterView,
							View view, int position, long id) {
						DebugUtil.debug("Diasmart",
								"sprTypes Item Selected Listener");

						if (position >= 0) {
							EntryType entryType = (EntryType) adapterView
									.getItemAtPosition(position);
							AddEditEntryActivity.this.setEntryType(entryType
									.getType());
						}
					}

					public void onNothingSelected(AdapterView<?> adapterView) {
						AddEditEntryActivity.this.setEntryType(-1);
					}
				});

		this.sprSubTypes.setPromptId(R.string.subtype);
		this.sprSubTypes
				.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
					public void onItemSelected(
							AdapterView<?> paramAnonymousAdapterView,
							View paramAnonymousView, int paramAnonymousInt,
							long paramAnonymousLong) {
						AddEditEntryActivity.this.setUnitOfMeasure();
					}

					public void onNothingSelected(
							AdapterView<?> paramAnonymousAdapterView) {
						AddEditEntryActivity.this.setUnitOfMeasure();
					}
				});
		((Button) findViewById(R.id.btnAddSubType))
				.setOnClickListener(new View.OnClickListener() {
					public void onClick(View paramAnonymousView) {
						Intent localIntent = new Intent(
								AddEditEntryActivity.this,
								SubTypeListActivity.class);
						localIntent.putExtra("edu.uwm.capstone.diasmart.type",
								AddEditEntryActivity.this.entryType);
						AddEditEntryActivity.this.startActivityForResult(
								localIntent, 2);
					}
				});

		AddEntryHelper.updateSpinnerAdapter(this.sprCategories,
				R.string.categories, this.categories);

		this.sprCategories
				.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
					public void onItemSelected(
							AdapterView<?> paramAnonymousAdapterView,
							View paramAnonymousView, int paramAnonymousInt,
							long paramAnonymousLong) {
						Category category = (Category) paramAnonymousAdapterView
								.getItemAtPosition(paramAnonymousInt);
						Spinner spinnerReminder = AddEditEntryActivity.this.sprReminder;
						int[] arrayOfInt = new int[1];
						arrayOfInt[0] = AddEditEntryActivity.this.entryType;
						AddEntryHelper.updateDefaultReminderForCategory(
								spinnerReminder, arrayOfInt, category.getId());
					}

					public void onNothingSelected(
							AdapterView<?> paramAnonymousAdapterView) {
					}
				});
		((Button) findViewById(R.id.btnAddCategory))
				.setOnClickListener(new View.OnClickListener() {
					public void onClick(View paramAnonymousView) {
						AddEditEntryActivity.this.startActivityForResult(
								new Intent(AddEditEntryActivity.this,
										CategoryListActivity.class), 0);
					}
				});

		TableRow tableRow = (TableRow) findViewById(R.id.trowReminder);
		if (this.mode == 1) {
			tableRow.setVisibility(TableRow.GONE);
		} else {
			tableRow.setVisibility(TableRow.VISIBLE);
		}

	}

	private void load(DatabaseHelper dh, long id) {
		this.entry = dh.getEntryDAO().getEntry(id);
		this.insertMode = false;
	}

	private void bind(DatabaseHelper dbh, Entry entry) {
		int i = 0;
		while (i >= this.sprTypes.getCount()) {

			setEntryType(entry.getType());
			if (entry.getId() >= 0L) {
				this.entryDate.setTimeInMillis(entry.getEntryDate());
				updateButtonEntryDate();
				String str = EntryTypeFactory.getInstance(entry.getType())
						.getEditableValue(new EntryContext(this),
								entry.getValue());
				this.edtValue.setText(str);
				if (entry.getNote() != null)
					this.edtNote.setText(entry.getNote());
			}
			if (entry.getCategoryId() != -1L) {
				long l = dbh.getCategoryDAO()
						.getInitialCategory(this.categories, new Date(), true)
						.getId();
				AddEntryHelper.updateCategorySelection(this.sprCategories, l);
				setSubTypeSpinner(entry.getSubTypeId());
			}
			if (((EntryType) this.sprTypes.getItemAtPosition(i)).getType() == entry
					.getType()) {
				this.sprTypes.setSelection(i);

			}
			i++;

		}

	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.dateFormat = android.text.format.DateFormat.getDateFormat(this);
		this.timeFormat = android.text.format.DateFormat.getTimeFormat(this);
		setContentView(R.layout.addeditentry);
		long id = -1L;
		Bundle globalVariables = getIntent().getExtras();
		if (globalVariables.size() > 0) {
			this.mode = globalVariables
					.getInt("edu.uwm.capstone.diasmart.EntryInfo.mode");
			if (this.mode == 1)
				id = globalVariables
						.getLong("edu.uwm.capstone.diasmart.EntryInfo.entryId");
		}
		DatabaseHelper dh = new DatabaseHelper(this);
		try {
			this.categories = dh.getCategoryDAO().getCategories();
			initialize(dh);
			if (id > 0L) {
				load(dh, id);
				if (this.entry == null) {
					showErrorDialog("Unexpected issue, could not find record with id '"
							+ id + "'");
					finish();
				}
			}

			bind(dh, this.entry);
			updateTitle();
			

		} catch (Exception e) {
			Log.e("Diasmart",
					"Unexpected error occured while trying "
							+ e.getLocalizedMessage());
		} finally {
			dh.close();
		}

	}

	private void updateTitle() {
		StringBuilder title = new StringBuilder("DiaSmart - ");
		if (this.mode == 0) {
			title.append("Add");
		} else
			title.append("Edit");

		this.setTitle(title);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	private void updateButtonEntryDate() {
		Log.d("Diasmart", "Update button Entry Date is called");
		this.btnEditDate.setText(this.dateFormat.format(this.entryDate
				.getTime()));
		this.btnEditTime.setText(this.timeFormat.format(this.entryDate
				.getTime()));
	}

	protected Dialog onCreateDialog(int id) {
		switch (id) {
		default:
			return null;
		case 0:
			return new DatePickerDialog(this, this.startDateSetListener,
					this.entryDate.get(1), this.entryDate.get(2),
					this.entryDate.get(5));

		case 1:
			return new TimePickerDialog(this, this.startTimeSetListener,
					this.entryDate.get(11), this.entryDate.get(12),
					android.text.format.DateFormat.is24HourFormat(this));

		case 2:
			AlertDialog localAlertDialog = new AlertDialog.Builder(this)
					.setIcon(android.R.drawable.ic_dialog_alert)
					.setTitle(R.string.entry_save_error_message)
					.setPositiveButton(R.string.ok,
							new DialogInterface.OnClickListener() {
								public void onClick(
										DialogInterface paramAnonymousDialogInterface,
										int paramAnonymousInt) {
								}
							}).create();
			if (!StringUtil.isEmpty(this.errorMessage))
				localAlertDialog.setMessage(this.errorMessage);
			return localAlertDialog;

		case 3:

		}
		return new AlertDialog.Builder(this)
				.setIcon(android.R.drawable.ic_dialog_alert)
				.setTitle(R.string.confirm_close_title)
				.setMessage(R.string.confirm_close_message)
				.setPositiveButton(R.string.ok,
						new DialogInterface.OnClickListener() {
							public void onClick(
									DialogInterface paramAnonymousDialogInterface,
									int paramAnonymousInt) {
								Log.d("Diasmart", "Alert Dialog Returned");
								AddEditEntryActivity.this.setResult(-1,
										AddEditEntryActivity.this
												.getIntentResult(false));
								AddEditEntryActivity.this.finish();
							}
						})
				.setNegativeButton(R.string.cancel,
						new DialogInterface.OnClickListener() {
							public void onClick(
									DialogInterface paramAnonymousDialogInterface,
									int paramAnonymousInt) {
							}
						}).create();
	}

	private Intent getIntentResult(boolean paramBoolean) {
		Intent localIntent = new Intent();
		Bundle localBundle = new Bundle();
		localBundle.putInt("edu.uwm.capstone.diasmart.EntryInfo.mode",
				this.mode);
		localBundle.putBoolean("edu.uwm.capstone.diasmart.EntryInfo.deleted",
				paramBoolean);
		localBundle.putLong("edu.uwm.capstone.diasmart.EntryInfo.entryId",
				this.entry.getId());
		localIntent.putExtras(localBundle);
		return localIntent;
	}

	private boolean getSubTypeVisibility() {
		return this.trowSubTypes.getVisibility() == 0;
	}

	public void setEntryType(int paramInt) {
		if (this.entryType != paramInt) {
			this.entryType = paramInt;
			handleTypeChange();
			setSubTypeSpinner(-1L);
			if (this.entryType == 5)
				Common.showBPNotice(this);
		}
	}

	private void handleTypeChange() {
		setUnitOfMeasure();
		setSubTypeValues();
		EntryType localEntryType = EntryTypeFactory.getInstance(this.entryType);
		if ((localEntryType instanceof EditableEntryType)) {
			Common.setNumericKeyboardType(this, this.edtValue,
					((EditableEntryType) localEntryType).getKeyboardType());
			return;
		}
		Common.setNumericKeyboardType(this, this.edtValue, "preference");
	}

	private void setSubTypeValues() {
		DatabaseHelper dh = new DatabaseHelper(this);
		try {
			SubType[] subTypes = dh.getSubTypeDAO().getSubTypes(this.entryType);
			if (subTypes.length == 0)
				setSubTypeVisibility(false);

			if (this.lastEntryType != this.entryType) {
				AddEntryHelper.updateSpinnerAdapter(this.sprSubTypes,
						R.string.subtypes, subTypes);
				this.lastEntryType = this.entryType;
				setSubTypeSpinner(-1L);
			}
			setSubTypeVisibility(true);

		} finally {
			dh.close();
		}
	}

	private void setSubTypeVisibility(boolean visibility) {
		TableRow tableRow = this.trowSubTypes;
		if (visibility)
			tableRow.setVisibility(TableRow.VISIBLE);
		else {
			tableRow.setVisibility(TableRow.GONE);
		}
	}

	private void setSubTypeSpinner(long paramLong) {
		for (int i = 0; i < this.sprSubTypes.getCount(); i++) {
			SubType localSubType = (SubType) this.sprSubTypes
					.getItemAtPosition(i);
			while ((localSubType.getId() != paramLong)
					&& ((paramLong != -1L) || (!localSubType.isUserDefault()))) {
				setUnitOfMeasure((SubType) this.sprSubTypes.getSelectedItem());
			}
			this.sprSubTypes.setSelection(i);
			this.sprSubTypes.setSelection(i, false);
		}
	}

	private void setUnitOfMeasure() {
		SubType localSubType = (SubType) this.sprSubTypes.getSelectedItem();
		if ((localSubType == null) || (localSubType.getUnit() == null)) {
			setUnitOfMeasure(null);
		}
		setUnitOfMeasure(localSubType);
	}

	private void setUnitOfMeasure(SubType paramSubType) {
		EntryType localEntryType = (EntryType) this.sprTypes.getSelectedItem();
		if (localEntryType != null) {
			String str = localEntryType.getMeasurementUnit(new EntryContext(
					this), paramSubType);
			((TextView) findViewById(R.id.txtUnitOfMeasure)).setText(str);
		}
	}

	@SuppressWarnings("deprecation")
	private void showErrorDialog(String paramString) {
		this.errorMessage = paramString;
		showDialog(2);
	}

	private void delete() {
		DatabaseHelper dbh = new DatabaseHelper(this);
		try {
			dbh.getEntryDAO().delete(this.entry);
		} finally {
			dbh.close();
		}
	}

	protected void onPrepareDialog(int id, Dialog dialog) {
		switch (id) {
		default:
			return;
		case 0:
			((DatePickerDialog) dialog).updateDate(this.entryDate.get(1),
					this.entryDate.get(2), this.entryDate.get(5));
			return;
		case 1:
		}
		((TimePickerDialog) dialog).updateTime(this.entryDate.get(11),
				this.entryDate.get(12));
	}

	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		if ((savedInstanceState != null)
				&& (savedInstanceState
						.containsKey("edu.uwm.capstone.diasmart.selectedDateTime"))) {
			long milliSeconds = savedInstanceState
					.getLong("edu.uwm.capstone.diasmart.selectedDateTime");
			this.entryDate.setTimeInMillis(milliSeconds);
			updateButtonEntryDate();
		}
		super.onRestoreInstanceState(savedInstanceState);
	}

	protected void onSaveInstanceState(Bundle savedInstanceState) {
		savedInstanceState.putLong(
				"edu.uwm.capstone.diasmart.selectedDateTime",
				this.entryDate.getTimeInMillis());
		super.onSaveInstanceState(savedInstanceState);
	}

}
